package com.garyme.hycloud.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import com.garyme.hycloud.model.HyFile;
import com.garyme.hycloud.model.HyFileBase;
import com.garyme.hycloud.model.HyUser;
import com.garyme.hycloud.model.RespData;
import com.garyme.hycloud.service.IFileDirObserverService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;



@RestController
@CrossOrigin
public class IndexController {
    @Resource
    IFileDirObserverService fileDirObserver;

    @Value("${hyFile.basePath}")
    private String  basePath;
    @Value("${hyFile.username}")
    private String  username;
    @Value("${hyFile.password}")
    private String password;


    @GetMapping("/file")
    public RespData<HyFileBase> index(@RequestParam("path") String path) {
        return RespData.success(fileDirObserver.listFileBase(basePath,path));
    }
    @GetMapping("/download")
    public void download(@RequestParam("path") String path,HttpServletRequest request, HttpServletResponse response) throws FileNotFoundException, UnsupportedEncodingException {
        getVideo(request,response,path,true);
    }

    /**
     * 获取视频流
     * @param response
     * @param fileName 视频存放信息索引
     * @return
     * @author xWang
     * @Date 2020-05-20
     */
    @GetMapping("/getVideo")
    public void getVideo(HttpServletRequest request, HttpServletResponse response, @RequestParam("path")String fileName,boolean isDownload) {
        if(fileName == null || fileName.trim().isEmpty()){
            return;
        }

        //视频资源存储信息
        response.reset();
        //获取从那个字节开始读取文件
        String rangeString = request.getHeader("Range");
        //log.info("getVideo获取视频资源:{},读取文件字节:{}",fileName,rangeString);
        try {
            //获取响应的输出流
            OutputStream outputStream = response.getOutputStream();
            File file = new File(basePath + "/"+ fileName);
            if(file.exists()){
                RandomAccessFile targetFile = new RandomAccessFile(file, "r");
                long fileLength = targetFile.length();
                //播放
                if(rangeString != null){

                    long range = Long.parseLong(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
                    //设置内容类型
                    response.setHeader("Content-Type", "video/mpeg4");
                    //Add 断点续传
                    if(isDownload){
                        //设置响应头，把文件名字设置好
                        response.setHeader("Content-Disposition", "attachment; filename="+ URLEncoder.encode(file.getName(),"UTF-8").replaceAll("\\+","%20"));
                    }
                    //设置此次相应返回的数据长度
                    response.setHeader("Content-Length", String.valueOf(fileLength - range));
                    //设置此次相应返回的数据范围
                    response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
                    //返回码需要为206，而不是200
                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                    //设定文件读取开始位置（以字节为单位）
                    targetFile.seek(range);
                }else {//下载

                    //设置响应头，把文件名字设置好
                    response.setHeader("Content-Disposition", "attachment; filename="+URLEncoder.encode(file.getName(),"UTF-8").replaceAll("\\+","%20") );
                    //设置文件长度
                    response.setHeader("Content-Length", String.valueOf(fileLength));
                    //解决编码问题
                    response.setHeader("Content-Type","application/octet-stream");
                }


                byte[] cache = new byte[1024 * 300];
                int flag;
                while ((flag = targetFile.read(cache))!=-1){
                    outputStream.write(cache, 0, flag);
                }
            }else {
                String message = "file:"+fileName+" not exists";
                //解决编码问题
                response.setHeader("Content-Type","application/json");
                outputStream.write(message.getBytes(StandardCharsets.UTF_8));
            }

            outputStream.flush();
            outputStream.close();

        } catch (FileNotFoundException e) {

        } catch (IOException e) {

        }
    }

    @DeleteMapping("/file/del")
    @SaCheckPermission("file:delete")
    public RespData<Boolean> deleteFile(@RequestParam("path") String path) {
        return RespData.success(fileDirObserver.delFileByName(basePath,path));
    }
    @PostMapping("/login")
    public RespData<Object> login(@RequestBody HyUser hyUser) {
        HashMap<String,String> result = new HashMap<>();
        if(hyUser == null || hyUser.getUsername() == null || hyUser.getPassword() == null){
            return RespData.fail("用户名或密码不能为空");
        }else{
            System.out.println("登陆成功");
            if(username.equals(hyUser.getUsername()) && password.equals(hyUser.getPassword())){
                StpUtil.login(101);
                System.out.println(StpUtil.getTokenValue());
                result.put("tokenName",StpUtil.getTokenName());
                result.put("tokenValue",StpUtil.getTokenValue());
                result.put("userId",String.valueOf(StpUtil.getLoginId()));
            }else{
                return RespData.fail("用户名或密码错误");
            }
        }


        return RespData.success(result);
    }

    @GetMapping("/logout")
    public RespData<Object> logout(){
        StpUtil.logout();
        return RespData.success("注销成功");
    }
    @PutMapping("/file/ren")
    @SaCheckPermission("file:rename")
    public RespData<Object> renameFile(@RequestParam("oldName") String oldName,@RequestParam("newName") String newName) {
        fileDirObserver.renameFile(basePath,oldName,newName);
        return RespData.success();
    }

    @PostMapping("/file/upload")
    @SaCheckPermission("file:upload")
    public RespData<HyFileBase> uploadMultipleFiles(@RequestParam("path") String path, MultipartFile file,@RequestParam("fileName") String fileName) throws IOException {
        fileDirObserver.uploadFile(file,basePath+"/"+path+"/",fileName);
        return RespData.success("上传成功");
    }
    @PostMapping("/file/upload/chunk")
    @SaCheckPermission("file:upload")
    public RespData<HyFileBase> uploadChunkFiles(MultipartFile file,String path,Integer chunkIdx,Integer chunkTotal,String fileName) throws IOException {
        fileDirObserver.chunkFile(file,basePath+"/"+path+"/",chunkIdx,chunkTotal,fileName);
        return RespData.success("上传成功");
    }

    @PostMapping("/file/upload/merge")
    @SaCheckPermission("file:upload")
    public RespData<HyFileBase> uploadMergeFiles(String path,String fileName,Integer chunkTotal) throws IOException {
        fileDirObserver.mergeFiles(basePath+"/"+path+"/",fileName,chunkTotal);
        return RespData.success("上传成功");
    }

    @PutMapping("/file/copy")
    @SaCheckPermission("file:copy")
    public RespData<Object> copyFile(@RequestParam("name") String oldName,@RequestParam("newPath") String newPath) {
        return RespData.success(fileDirObserver.copyFile(basePath,oldName,newPath));
    }
    @PutMapping("/file/cut")
    @SaCheckPermission("file:cut")
    public RespData<Object> cutFile(@RequestParam("name") String oldName,@RequestParam("newPath") String newPath) {
        fileDirObserver.moveFile(basePath,oldName,newPath);
        return RespData.success();
    }
    @PutMapping("/file/newDir")
    @SaCheckPermission("file:new:dir")
    public RespData<Object> newDir(@RequestParam("name") String name,@RequestParam("path") String path){
        fileDirObserver.newDir(basePath,name,path);
        return RespData.success();
    }


}
